﻿using Autofac;
using Autofac.Core;
using Autofac.Integration.Mvc;
using FluentValidation;
using Nop.Core.Data;
using Nop.Core.Infrastructure;
using Nop.Core.Infrastructure.DependencyManagement;
using Nop.Data;
using Nop.Plugin.Misc.Reservations.Data;
using Nop.Plugin.Misc.Reservations.Models;
using Nop.Plugin.Misc.Reservations.Services;
using Nop.Plugin.Misc.Reservations.Validators;

namespace Nop.Plugin.Misc.Reservations 
{
    public class ReservationDependencyRegistrar : IDependencyRegistrar 
    {

        #region Private Fields

        private const string CONTEXT_NAME = "nop_object_context_reservation";

        #endregion

        #region Implementation of IDependencyRegistrar

        public void Register(ContainerBuilder builder, ITypeFinder typeFinder) 
        {
            //Load custom data settings
            var dataSettingsManager = new DataSettingsManager();
            DataSettings dataSettings = dataSettingsManager.LoadSettings();
            //Register custom object context
            builder
                .Register<IDbContext>(c => RegisterIDbContext(c, dataSettings))
                .Named<IDbContext>(CONTEXT_NAME)
                .InstancePerHttpRequest();
            builder
                .Register(c => RegisterIDbContext(c, dataSettings))
                .InstancePerHttpRequest();
            //Register services
            builder
                .RegisterType<ReservationService>()
                .As<IReservationService>();
            //Override the repository injection
            builder
                .RegisterType<EfRepository<Reservation>>()
                .As<IRepository<Reservation>>()
                .WithParameter(ResolvedParameter.ForNamed<IDbContext>(CONTEXT_NAME))
                .InstancePerHttpRequest();
            // Reservation Business
            builder
                .RegisterType<ReservationBusiness>()
                .As<IReservationBusiness>()
                .InstancePerHttpRequest();
            // Reservation Work Context
            builder
                .RegisterType<ReservationWorkContext>()
                .As<IReservationWorkContext>()
                .InstancePerHttpRequest();
            // Register FluentValidation
            builder
                .RegisterType<ReservationDailyValidator>()
                .As<AbstractValidator<ReservationViewModel>>()
                .InstancePerHttpRequest();
        }

        public int Order 
        {
            get { return 0; }
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Registers the I db context.
        /// </summary>
        /// <param name="componentContext">The component context.</param>
        /// <param name="dataSettings">The data settings.</param>
        /// <returns></returns>
        private ReservationObjectContext RegisterIDbContext(IComponentContext componentContext, DataSettings dataSettings) 
        {
            string dataConnectionStrings;
            if (dataSettings != null && dataSettings.IsValid()) 
            {
                dataConnectionStrings = dataSettings.DataConnectionString;
            } 
            else 
            {
                dataConnectionStrings = componentContext.Resolve<DataSettings>().DataConnectionString;
            }
            return new ReservationObjectContext(dataConnectionStrings);
        }

        #endregion
    }
}
